home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * *
- * Copyright (C) 1996, Silicon Graphics, Inc. *
- * All Rights Reserved. *
- * *
- * The files in this subtree contain UNPUBLISHED PROPRIETARY SOURCE *
- * CODE of Silicon Graphics, Inc.; the contents of these files may *
- * not be disclosed to third parties, copied or duplicated in any *
- * form, in whole or in part, without the prior written permission *
- * of Silicon Graphics, Inc. *
- * *
- * RESTRICTED RIGHTS LEGEND: *
- * Use, duplication or disclosure by the Government is subject to *
- * restrictions as set forth in subdivision (c)(1)(ii) of the Rights in *
- * Technical Data and Computer Software clause at DFARS 252.227-7013, *
- * and/or in similar or successor clauses in the FAR, DOD or NASA FAR *
- * Supplement. Unpublished - rights reserved under the Copyright Laws *
- * of the United States. *
- * *
- * THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, *
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY *
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. *
- * *
- * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, *
- * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY *
- * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, *
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY *
- * THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR *
- * PERFORMANCE OF THIS SOFTWARE. *
- **************************************************************************/
-
- /*
- Author : Patrick Bouchaud & Paul Hansen
- galaad@neu.sgi.com hansen@engr.sgi.com
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <GL/gl.h>
- #include <bstring.h>
- #include <math.h>
- #include "data.h"
-
- #include "culling.h"
-
- #define ABS(x) ((x)<0?-(x):(x))
-
- Segment* alloc_Segment(Segment*);
- Vertex* alloc_Vertex(Vertex*);
- Face* alloc_Face(Face*);
- Edge* alloc_Edge(Edge*);
- Volume* alloc_Volume(Volume*);
-
- static GLvoid GetLOD(float, float, int*, int*);
-
- /* These functions can be expanded to match image to terrain */
- #define LAT_CONV ((GLdouble)NUMTILE_S/NUM_LATITUDE/D_LATITUDE)
- #define LON_CONV ((GLdouble)NUMTILE_T/NUM_LONGITUDE/D_LONGITUDE)
- #define TILE_TO_ELEV_LAT(x) ((x)*(NUM_LATITUDE-1)*6144/6000/NUMTILE_S)
- #define TILE_TO_ELEV_LON(x) ((x)*(NUM_LONGITUDE-1)*6144/6000/NUMTILE_T)
-
- extern float obsLat, obsLon, obsAlt, texture_select;
-
- float cvec[2][2][3] = {{{1, 0, 0}, {0, 1, 0}}, {{0, 0, 1}, {1, 1, 0}}};
- /* float cvec[9][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0},
- {0, 1, 1}, {1, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; */
- float row_bottom[NUMTILE_S][2];
- float row_top[NUMTILE_S][2];
- float row_perc_b[NUMTILE_S][2];
- float row_perc_t[NUMTILE_S][2];
- float col_left[NUMTILE_T][2];
- float col_right[NUMTILE_T][2];
- float col_perc_l[NUMTILE_T][2];
- float col_perc_r[NUMTILE_T][2];
- GLdouble combMat[16];
-
- /*---------------------------------------------------------------------------*
- * InitializeRowData -- establishes tile boundaries in lat/lon space *
- *---------------------------------------------------------------------------*/
-
- void
- InitializeRowData(lat_stride, lon_stride)
- {
- register int j, tmp;
- float inv_latstride = (float)1.0 / lat_stride;
- float inv_lonstride = (float)1.0 / lon_stride;
-
- for(j=0; j<NUMTILE_S; ++j) {
- row_bottom[j][0] = TILE_TO_ELEV_LAT((float)j);
- row_top[j][0] = row_bottom[j][1] = TILE_TO_ELEV_LAT((float)j+0.5);
- row_top[j][1] = TILE_TO_ELEV_LAT((float)(j+1));
-
- tmp = (int)(row_bottom[j][0] * inv_latstride) * lat_stride;
- if((float)tmp != row_bottom[j][0]) tmp += lat_stride;
- row_perc_b[j][0] = ((float)tmp - row_bottom[j][0]) * inv_latstride;
-
- tmp = (int)(row_top[j][0] * inv_latstride) * lat_stride;
- row_perc_t[j][0] = (row_top[j][0] - (float)tmp) * inv_latstride;
-
- tmp = (int)(row_bottom[j][1] * inv_latstride) * lat_stride;
- if((float)tmp != row_bottom[j][1]) tmp += lat_stride;
- row_perc_b[j][1] = ((float)tmp - row_bottom[j][1]) * inv_latstride;
-
- tmp = (int)(row_top[j][1] * inv_latstride) * lat_stride;
- row_perc_t[j][1] = (row_top[j][1] - (float)tmp) * inv_latstride;
- }
- for(j=0; j<NUMTILE_T; ++j) {
- col_left[j][0] = TILE_TO_ELEV_LON((float)j);
- col_right[j][0] = col_left[j][1] = TILE_TO_ELEV_LON((float)j+0.5);
- col_right[j][1] = TILE_TO_ELEV_LON((float)(j+1));
-
- tmp = (int)(col_left[j][0] * inv_lonstride) * lon_stride;
- if((float)tmp != col_left[j][0]) tmp += lon_stride;
- col_perc_l[j][0] = ((float)tmp - col_left[j][0]) * inv_lonstride;
-
- tmp = (int)(col_right[j][0] * inv_lonstride) * lon_stride;
- col_perc_r[j][0] = (col_right[j][0] - (float)tmp) * inv_lonstride;
-
- tmp = (int)(col_left[j][1] * inv_lonstride) * lon_stride;
- if((float)tmp != col_left[j][1]) tmp += lon_stride;
- col_perc_l[j][1] = ((float)tmp - col_left[j][1]) * inv_lonstride;
-
- tmp = (int)(col_right[j][1] * inv_lonstride) * lon_stride;
- col_perc_r[j][1] = (col_right[j][1] - (float)tmp) * inv_lonstride;
- }
- }
-
- /*---------------------------------------------------------------------------*
- * XCullDraw -- terrain is rendered as a series of textured tiles. Each tile
- * is rendered as 9 areas, some of which may not be in the viewing area.
- * The reader is referred to the "tiling_doc.sc" for diagrams and additional
- * description.
- *---------------------------------------------------------------------------*/
-
- #define LAT_METERS_TO_TILES(x) ((x)*NUMTILE_S*6000/6144/(NUM_LATITUDE-1)/D_LATITUDE)
- #define LON_METERS_TO_TILES(x) ((x)*NUMTILE_T*6000/6144/(NUM_LONGITUDE-1)/D_LONGITUDE)
- #define SCONV(x) (((x)-s_offset)*ISCALE_S)
- #define TCONV(x) (((x)-t_offset)*ISCALE_T)
-
- #ifdef TEXTURED
- #define DO_VERTEX(lon, alt, lat) \
- glTexCoord2f(SCONV(lat), TCONV(lon)); \
- glVertex3f(lon*D_LONGITUDE, alt, lat*D_LATITUDE);
- #else
- #define DO_VERTEX(lon, alt, lat) \
- glVertex3f(lon*D_LONGITUDE, alt, lat*D_LATITUDE);
- #endif
-
- #define STRIP_SETUP \
- bypass=0; \
- lon1 = l_lon[qrow][idx-1]; \
- if(lon1 >= right && lon2 >= right) bypass=1; \
- if(lon1 >= r_lon[qrow][idx-1] && lon2 >= r_lon[qrow][idx]) bypass=1; \
- if(!bypass) { \
- lon = lon1 < lon2 ? lon1 : lon2; \
- l_lon_i = (int)(lon * inv_lonstride) * lon_stride; \
- if(lon == col_left[tilecol][qcol]) \
- perc_l = col_perc_l[tilecol][qcol]; \
- else perc_l = 0.0; \
- lon2 = r_lon[qrow][idx]; \
- lon1 = r_lon[qrow][idx-1]; \
- lon = lon1 > lon2 ? lon1 : lon2; \
- if(lon > right) { \
- lon = right; \
- perc_r = col_perc_r[tilecol][qcol]; \
- } \
- else perc_r = 0.0; \
- r_lon_i = (int)(lon * inv_lonstride) * lon_stride; \
- if((float)r_lon_i != lon) \
- r_lon_i += lon_stride; \
- \
- lon1 = (float)l_lon_i; \
- lon2 = lon1 + lon_stride; \
- alt3 = &Terrain[(int)lat1][(int)lon2]; \
- alt4 = &Terrain[(int)lat2][(int)lon2]; \
- alt1 = alt3 - lon_stride; \
- alt2 = alt4 - lon_stride; \
- }
-
- int
- XCullDraw(
- float altmin,
- float altmax,
- int lat_stride,
- int lon_stride
- )
- {
- register float lat, lat1, lat2, lat3, lon, lon1, lon2, lon3, s_offset, t_offset;
- int bypass, idx, j, tilerow, tilecol, qrow, qcol, minlod, maxlod;
- float dlat_stride, lonmin, lonmax, latmin, latmax, unused;
- float dlon_stride, inv_latstride, inv_lonstride;
- float jminf, jmin_tile, jmaxf, jmax_tile, jval, iminf, imaxf;
- static float l_lon[2][MAXGRID_LAT], r_lon[2][MAXGRID_LAT];
- float lon_min[2], lon_max[2], right, dist, size;
- int b_lat_i[2], t_lat_i, l_lon_i, r_lon_i;
- float perc_l, perc_r, perc_t[2], perc_b[2], *alt1, *alt2, *alt3, *alt4, atmp, asave;
- GLdouble vec1[4];
-
- xdim = (float)((NUM_LONGITUDE-1)/lon_stride*lon_stride)*D_LONGITUDE;
- zdim = (float)((NUM_LATITUDE-1)/lat_stride*lat_stride)*D_LATITUDE;
-
- inv_latstride = (float)1.0 / lat_stride;
- inv_lonstride = (float)1.0 / lon_stride;
-
- /*
- compute the 2 concave polygon resulting from the projection
- of the viewing frustum onto the planes defined by Y=altmax, Y=altmin
- */
- deleteVolume( pyramid );
- pyramid = newFrustumPyramid();
- BBoxClip( pyramid, 0., xdim, altmin, altmax, 0., zdim );
-
- /*
- get min and max x-values of the projected viewing frustrums
- derive min and max j-indices into the elevation array.
- After this, for each tile row, we gather data on the
- min and max values at the culling boundary for each
- "strip" to be rendered.
- */
- getMinMaxLat(pyramid, &latmin, &latmax);
- jmin_tile = LAT_METERS_TO_TILES(latmin);
- jmax_tile = LAT_METERS_TO_TILES(latmax);
- jminf = latmin/D_LATITUDE;
- jmaxf = latmax/D_LATITUDE;
- *(unsigned long*)&unused = 0xbfbfbfbf;
- dlat_stride = lat_stride * D_LATITUDE;
- for(jval=jminf, tilerow=(int)jmin_tile; tilerow<=(int)jmax_tile; ++tilerow) {
- lon_max[0] = lon_max[1] = (float)-1;
- lon_min[0] = lon_min[1] = (float)NUM_LONGITUDE;
- for(qrow=0; qrow<2; ++qrow) {
- l_lon[qrow][0] = r_lon[qrow][0] = unused;
- if(jval >= row_top[tilerow][qrow]) continue;
- if(jval >= jmaxf) continue;
- b_lat_i[qrow] = (int)(jval * inv_latstride) * lat_stride;
- if(jval == row_bottom[tilerow][qrow])
- perc_b[qrow] = row_perc_b[tilerow][qrow];
- else perc_b[qrow] = 0.0;
-
- jval = row_top[tilerow][qrow];
- if(jval > jmaxf) {
- jval = jmaxf;
- perc_t[qrow] = 0.0;
- }
- else perc_t[qrow] = row_perc_t[tilerow][qrow];
- t_lat_i = (int)(jval * inv_latstride) * lat_stride;
- if((float)t_lat_i != jval)
- t_lat_i += lat_stride;
-
- lat = b_lat_i[qrow] * D_LATITUDE;
- for(idx=0, j=b_lat_i[qrow]; j<=t_lat_i; j+=lat_stride, idx++, lat+=dlat_stride) {
- if(getMinMaxLon(pyramid, lat, &l_lon[qrow][idx], &r_lon[qrow][idx])) {
- l_lon[qrow][idx] *= INV_DLON;
- r_lon[qrow][idx] *= INV_DLON;
- if(l_lon[qrow][idx] < lon_min[qrow]) lon_min[qrow] = l_lon[qrow][idx];
- if(r_lon[qrow][idx] > lon_max[qrow]) lon_max[qrow] = r_lon[qrow][idx];
- }
- else l_lon[qrow][idx] = r_lon[qrow][idx] = -1.0;
- }
- l_lon[qrow][idx] = r_lon[qrow][idx] = unused;
- if(l_lon[qrow][0] == -1.0) {
- l_lon[qrow][0] = l_lon[qrow][1];
- r_lon[qrow][0] = r_lon[qrow][1];
- }
- if(idx > 1 && l_lon[qrow][idx-1] == -1) {
- l_lon[qrow][idx-1] = l_lon[qrow][idx-2];
- r_lon[qrow][idx-1] = r_lon[qrow][idx-2];
- }
- }
-
- lonmin = INF(lon_min[0], lon_min[1]);
- lonmax = SUP(lon_max[0], lon_max[1]);
- iminf = lonmin * NUMTILE_T * 6000 / 6144 / (NUM_LONGITUDE-1);
- imaxf = lonmax * NUMTILE_T * 6000 / 6144 / (NUM_LONGITUDE-1);
-
- /* data collection finished; now do rendering for this tile row */
- glColor3f(1.0, 1.0, 1.0);
- for(tilecol=(int)iminf; tilecol <= (int)imaxf; ++tilecol) {
- #ifdef TEXTURED
- GetLOD(row_top[tilerow][0], col_right[tilecol][0], &minlod, &maxlod);
- if(texture_select) {
- glBindTextureEXT(GL_TEXTURE_2D, tilecol*NUMTILE_S+tilerow+1);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL_SGIS, minlod);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD_SGIS, (float)minlod);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL_SGIS, maxlod);
- }
- #endif
- for(qcol=0; qcol<2; ++qcol) {
- for(qrow=0; qrow<2; ++qrow) {
- if(l_lon[qrow][0] == unused) continue;
- if(lon_min[qrow] >= (right=col_right[tilecol][qcol]) ||
- lon_min[qrow] >= lon_max[qrow]) {
- lon_min[qrow] = right;
- continue;
- }
-
- #ifdef TEXTURED
- s_offset = row_bottom[tilerow][qrow];
- t_offset = col_left[tilecol][qcol];
- if(texture_select)
- glTexParameteri(GL_TEXTURE_2D, GL_QUAD_TEXTURE_SELECT_SGIS, (qcol<<1)|qrow);
- else {
- glBindTextureEXT(GL_TEXTURE_2D, ((tilecol*NUMTILE_S+tilerow<<2)|(qcol<<1)|qrow)+1);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL_SGIS, minlod);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD_SGIS, (float)minlod);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL_SGIS, maxlod);
- }
- #else
- glColor3fv(cvec[qrow][qcol]);
- #endif
- idx = 1;
- lat1 = (float)b_lat_i[qrow];
- lat2 = lat1 + lat_stride;
- if(perc_b[qrow]) { /* do bottom tile stitching */
- if((lon2 = l_lon[qrow][idx]) == unused) continue;
- STRIP_SETUP
- if(!bypass) {
- lat3 = row_bottom[tilerow][qrow];
-
- if(perc_l) { /* AREA #1 -- see "tiling_doc.sc" */
- lon3 = col_left[tilecol][qcol];
- glBegin(GL_TRIANGLE_FAN);
- if(perc_l + perc_b[qrow] > 1.0) {
- lat = lat1+perc_l*lat_stride;
- DO_VERTEX(lon3, *alt3+perc_l*(*alt2-*alt3), lat);
- }
- DO_VERTEX(lon3, *alt4+perc_l*(*alt2-*alt4), lat2);
- DO_VERTEX(lon2, *alt4, lat2);
- DO_VERTEX(lon2, atmp= *alt4+perc_b[qrow]*(*alt3-*alt4), lat3);
- if(perc_l + perc_b[qrow] > 1.0) {
- lon = lon1+perc_b[qrow]*lon_stride;
- DO_VERTEX(lon, *alt2+perc_b[qrow]*(*alt3-*alt2), lat3);
- }
- atmp = atmp + perc_l * ((*alt2+perc_b[qrow]*(*alt1-*alt2)) - atmp);
- DO_VERTEX(lon3, atmp, lat3);
- glEnd();
- lon1 = lon2; lon2 += lon_stride;
- alt1 = alt3; alt3 += lon_stride;
- alt2 = alt4; alt4 += lon_stride;
- }
- lon3 = lon1 + perc_b[qrow] * lon_stride;
- asave = *alt2 + perc_b[qrow] * (*alt1-*alt2);
-
- /* AREA #2 -- see "tiling_doc.sc" */
- for(; lon2<=(float)r_lon_i-perc_r; lon1=lon2, lon2+=lon_stride, lon3+=lon_stride,
- alt1=alt3, asave=atmp, alt3+=lon_stride, alt2=alt4, alt4+=lon_stride) {
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon1, *alt2, lat2);
- DO_VERTEX(lon2, *alt4, lat2);
- DO_VERTEX(lon2, atmp= *alt4+perc_b[qrow]*(*alt3-*alt4), lat3);
- DO_VERTEX(lon3, *alt2+perc_b[qrow]*(*alt3-*alt2), lat3);
- DO_VERTEX(lon1, asave, lat3);
- glEnd();
- }
-
- if(perc_r) { /* AREA #3 -- see "tiling_doc.sc" */
- lon3 = right;
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon1, *alt2, lat2);
- DO_VERTEX(lon3, atmp= *alt2+perc_r*(*alt4-*alt2), lat2);
- atmp = atmp + perc_b[qrow] * ((*alt1+perc_r*(*alt3-*alt1)) - atmp);
- if(perc_r > perc_b[qrow]) {
- DO_VERTEX(lon3, atmp, lat3);
- lon = lon1+perc_b[qrow]*lon_stride;
- DO_VERTEX(lon, *alt2+perc_b[qrow]*(*alt3-*alt2), lat3);
- }
- else {
- lat = lat2-perc_r*lat_stride;
- DO_VERTEX(lon3, *alt2+perc_r*(*alt3-*alt2), lat);
- DO_VERTEX(lon3, atmp, lat3);
- }
- DO_VERTEX(lon1, *alt2+perc_b[qrow]*(*alt1-*alt2), lat3);
- glEnd();
- }
- }
- lat1 = lat2; lat2 += lat_stride;
- if(right > l_lon[qrow][0])
- l_lon[qrow][0] = right;
- idx++;
- }
- for(; ; idx++, lat1=lat2, lat2+=lat_stride) { /* now do main section */
- if((lon2 = l_lon[qrow][idx]) == unused) break;
- if(l_lon[qrow][idx+1]==unused && perc_t[qrow]) break;
- STRIP_SETUP
- if(!bypass) {
-
- if(perc_l) { /* AREA #4 -- see "tiling_doc.sc" */
- lon3 = col_left[tilecol][qcol];
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon2, *alt3, lat1);
- DO_VERTEX(lon3, *alt3+perc_l*(*alt1-*alt3), lat1);
- lat = lat1+perc_l*lat_stride;
- DO_VERTEX(lon3, *alt3+perc_l*(*alt2-*alt3), lat);
- DO_VERTEX(lon3, *alt4+perc_l*(*alt2-*alt4), lat2);
- DO_VERTEX(lon2, *alt4, lat2);
- glEnd();
- lon1 = lon2; lon2 += lon_stride;
- alt1 = alt3; alt3 += lon_stride;
- alt2 = alt4; alt4 += lon_stride;
- }
-
- /* AREA #5 -- see "tiling_doc.sc" */
- glBegin(GL_TRIANGLE_STRIP);
- for(; lon1<=(float)r_lon_i-perc_r; lon1+=lon_stride, alt1+=lon_stride, alt2+=lon_stride) {
- DO_VERTEX(lon1, *alt1, lat1);
- DO_VERTEX(lon1, *alt2, lat2);
- }
- glEnd();
-
- if(perc_r) { /* AREA #6 -- see "tiling_doc.sc" */
- lon2 = lon1; lon1 -= lon_stride;
- alt3 = alt1; alt1 -= lon_stride;
- alt4 = alt2; alt2 -= lon_stride;
- lon3 = right;
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon1, *alt2, lat2);
- DO_VERTEX(lon3, *alt2+perc_r*(*alt4-*alt2), lat2);
- lat = lat2+perc_r*(lat1-lat2);
- DO_VERTEX(lon3, *alt2+perc_r*(*alt3-*alt2), lat);
- DO_VERTEX(lon3, *alt1+perc_r*(*alt3-*alt1), lat1);
- DO_VERTEX(lon1, *alt1, lat1);
- glEnd();
- }
- }
- if(right > l_lon[qrow][idx-1])
- l_lon[qrow][idx-1] = right;
- }
- if(perc_t[qrow]) { /* do top tile stitching */
- if((lon2 = l_lon[qrow][idx]) == unused) continue;
- STRIP_SETUP
- if(!bypass) {
- lat3 = row_top[tilerow][qrow];
-
- if(perc_l) { /* AREA #7 -- see "tiling_doc.sc" */
- lon3 = col_left[tilecol][qcol];
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon2, *alt3, lat1);
- DO_VERTEX(lon3, atmp= *alt3+perc_l*(*alt1-*alt3), lat1);
- atmp = atmp + perc_t[qrow] * ((*alt4+perc_l*(*alt2-*alt4)) - atmp);
- if(perc_l > perc_t[qrow]) {
- DO_VERTEX(lon3, atmp, lat3);
- lon = lon2-perc_t[qrow]*lon_stride;
- DO_VERTEX(lon, *alt3+perc_t[qrow]*(*alt2-*alt3), lat3);
- }
- else {
- lat = lat1+perc_l*lat_stride;
- DO_VERTEX(lon3, *alt3+perc_l*(*alt2-*alt3), lat);
- DO_VERTEX(lon3, atmp, lat3);
- }
- DO_VERTEX(lon2, *alt3+perc_t[qrow]*(*alt4-*alt3), lat3);
- glEnd();
- lon1 = lon2; lon2 += lon_stride;
- alt1 = alt3; alt3 += lon_stride;
- alt2 = alt4; alt4 += lon_stride;
- }
- lon3 = lon2 - perc_t[qrow] * lon_stride;
- asave = *alt1 + perc_t[qrow] * (*alt2-*alt1);
-
- /* AREA #8 -- see "tiling_doc.sc" */
- for(; lon2<=(float)r_lon_i-perc_r; lon1=lon2, lon2+=lon_stride, lon3+=lon_stride,
- alt1=alt3, alt3+=lon_stride, alt2=alt4, alt4+=lon_stride) {
- glBegin(GL_TRIANGLE_FAN);
- DO_VERTEX(lon2, *alt3, lat1);
- DO_VERTEX(lon1, *alt1, lat1);
- DO_VERTEX(lon1, asave, lat3);
- DO_VERTEX(lon3, *alt3+perc_t[qrow]*(*alt2-*alt3), lat3);
- DO_VERTEX(lon2, asave= *alt3+perc_t[qrow]*(*alt4-*alt3), lat3);
- glEnd();
- }
-
- if(perc_r) { /* AREA #9 -- see "tiling_doc.sc" */
- lon3 = col_right[tilecol][qcol];
- glBegin(GL_TRIANGLE_FAN);
- if(perc_r + perc_t[qrow] > 1.0) {
- lat = lat2-perc_r*lat_stride;
- DO_VERTEX(lon3, *alt2+perc_r*(*alt3-*alt2), lat);
- }
- DO_VERTEX(lon3, *alt1+perc_r*(*alt3-*alt1), lat1);
- DO_VERTEX(lon1, *alt1, lat1);
- DO_VERTEX(lon1, atmp= *alt1+perc_t[qrow]*(*alt2-*alt1), lat3);
- if(perc_r + perc_t[qrow] > 1.0) {
- lon = lon2-perc_t[qrow]*lon_stride;
- DO_VERTEX(lon, *alt3+perc_t[qrow]*(*alt2-*alt3), lat3);
- }
- atmp = atmp + perc_r * ((*alt3+perc_t[qrow]*(*alt4-*alt3)) - atmp);
- DO_VERTEX(lon3, atmp, lat3);
- glEnd();
- }
- }
- if(right > l_lon[qrow][idx-1])
- l_lon[qrow][idx-1] = right;
- idx++;
- }
- if(right > l_lon[qrow][idx])
- l_lon[qrow][idx-1] = right;
- }
- }
- }
- /* fprintf(stderr, "one tile row\n"); */
- }
- }
-
- /*---------------------------------------------------------------------------*
- * GetLOD -- calculates a range of mipmap levels to be used for tile
- * Calculates distance to point (lat,lon), which is taken as a ratio
- * to a standard distance at which level 0 appears to be full size,
- * i.e., neither mag nor min. We then take the log of the ratio by
- * extracting the exponent of the floating point value.
- *---------------------------------------------------------------------------*/
-
- static GLvoid
- GetLOD(
- float lat,
- float lon,
- int *minlod,
- int *maxlod
- ) {
- register GLfloat atmp, dist;
- GLfloat size;
-
- atmp = obsAlt/* - Terrain[(int)lat][(int)lon] */;
- if(atmp < 0) atmp = 0;
- lat = ABS(lat*D_LATITUDE-obsLat);
- lon = ABS(lon*D_LONGITUDE-obsLon);
- if(lat > lon)
- dist = sqrt(lat*lat+atmp*atmp);
- else dist = sqrt(lon*lon+atmp*atmp);
- if(dist==0) size = 256.0;
- else size = dist/(7000 * atmp/dist);
- *minlod = ((*(unsigned long*)&size>>23)&0xff)-127;
- if(*minlod < 0) *minlod = 0;
- *maxlod = *minlod+2;
- if(*maxlod > 4) *maxlod = 8;
- /*
- fprintf(stderr, "lat: %f lon: %f atmp: %f size: %f minlod: %ld\n", lat, lon, obsAlt, size, *minlod);
- */
- }
-
- /*---------------------------------------------------------------------------*/
- /* newFrustumPyramid
- /*---------------------------------------------------------------------------*/
-
- #define FrontLeftBottom 0
- #define BackLeftBottom 1
- #define FrontRightBottom 2
- #define BackRightBottom 3
- #define FrontRightTop 4
- #define BackRightTop 5
- #define FrontLeftTop 6
- #define BackLeftTop 7
-
- #define LeftFace 0
- #define RightFace 1
- #define TopFace 2
- #define BottomFace 3
- #define FrontFace 4
- #define BackFace 5
-
- static Volume *
- newFrustumPyramid()
- {
- GLint i, vp[4];
- GLdouble projMat[16], modelMat[16],
- x0, y0, z0, x1, y1, z1,
- *normal;
- Volume *volume;
- Face *Polygon[6], *face;
- Edge *edge;
- Segment *segment;
- Vertex *Corner[8], *v, *v0, *v1, *v2, *v3;
-
- /*
- Allocate the data structure for the new volume :
- ------------------------------------------------
- pyramid = 8 vertex / 6 faces / 12 segments
- */
- volume = alloc_Volume( NULL );
-
- volume->numVertex = 8;
- for (i=0; i<8; i++) Corner[i] = alloc_Vertex(NULL);
- v = volume->firstVertex = Corner[0];
- v->last = NULL;
- for (i=1; i<8; i++)
- {
- v->next = Corner[i];
- v->next->last = v;
- v = v->next;
- }
- v->next = NULL;
- volume->lastVertex = v;
-
- volume->numSegment = 0;
- volume->firstSegment = volume->lastSegment = NULL;
-
- volume->numFace = 6;
- for (i=0; i<6; i++) Polygon[i] = newFace( 4, NULL );
- face = volume->firstFace = Polygon[0];
- face->last = NULL;
- for (i=1; i<6; i++)
- {
- face->next = Polygon[i];
- face->next->last = face;
- face = face->next;
- }
- face->next = NULL;
- volume->lastFace = face;
-
- /*
- compute the 3D coordinates of the 8 corners of the viewing
- ----------------------------------------------------------
- frustum, as resulting from the gluUnProject( current matrix )
- of the corners of the current viewport, with zval={0.,1.}
- */
- glGetDoublev( GL_PROJECTION_MATRIX, projMat );
- glGetDoublev( GL_MODELVIEW_MATRIX, modelMat );
- glGetIntegerv( GL_VIEWPORT, vp );
-
- x0 = (GLdouble) vp[0];
- y0 = (GLdouble) vp[1];
- x1 = (GLdouble) (vp[0]+vp[2]-1);
- y1 = (GLdouble) (vp[1]+vp[3]-1);
-
- #define setVertex( wx, wy, wz, angle ) \
- v = Corner[angle];\
- v->in = 1;\
- gluUnProject( wx, wy, wz, modelMat, projMat, vp, &v->x, &v->y, &v->z );
-
- setVertex( x0, y0, 0., FrontLeftBottom );
- setVertex( x0, y0, 1., BackLeftBottom );
- setVertex( x1, y0, 0., FrontRightBottom );
- setVertex( x1, y0, 1., BackRightBottom );
- setVertex( x1, y1, 0., FrontRightTop );
- setVertex( x1, y1, 1., BackRightTop );
- setVertex( x0, y1, 0., FrontLeftTop );
- setVertex( x0, y1, 1., BackLeftTop );
-
- /*
- now compute the 6 normals of each face of the viewing frustum
- -------------------------------------------------------------
- from the previously computed corners.
- The normals are NOT normalized, and are computed according to
- normal = (corner0,corner1)^(corner0,corner3)
-
- the viewing frustum is defined by the 6 inequations :
- normal[face].(corner[face],M) >= 0
- we compute now the coefficients of these equations
- */
- #define setFace( side, angle0, angle1, angle2, angle3 )\
- \
- face = Polygon[side];\
- v0 = Corner[angle0];\
- v1 = Corner[angle1];\
- v2 = Corner[angle2];\
- v3 = Corner[angle3];\
- x0 = v1->x-v0->x; y0 = v1->y-v0->y; z0 = v1->z-v0->z;\
- x1 = v3->x-v0->x; y1 = v3->y-v0->y; z1 = v3->z-v0->z;\
- normal = face->equation;\
- normal[0] = y0*z1 - y1*z0;\
- normal[1] = x1*z0 - x0*z1;\
- normal[2] = x0*y1 - x1*y0;\
- normal[3] = -(v0->x*normal[0]+v0->y*normal[1]+v0->z*normal[2]);\
- \
- edge = face->firstEdge;\
- edge->segment = newSegment( volume, v0, v1 );\
- edge->inverted = (edge->segment->start==v1);\
- edge = edge->next;\
- edge->segment = newSegment( volume, v1, v2 );\
- edge->inverted = (edge->segment->start==v2);\
- edge = edge->next;\
- edge->segment = newSegment( volume, v2, v3 );\
- edge->inverted = (edge->segment->start==v3);\
- edge = edge->next;\
- edge->segment = newSegment( volume, v3, v0 );\
- edge->inverted = (edge->segment->start==v0);
-
- face = volume->firstFace;
- setFace( LeftFace,
- BackLeftBottom, BackLeftTop,
- FrontLeftTop, FrontLeftBottom
- );
-
- face = face->next;
- setFace( RightFace,
- BackRightBottom, FrontRightBottom,
- FrontRightTop, BackRightTop
- );
-
- face = face->next;
- setFace( FrontFace,
- FrontLeftBottom, FrontLeftTop,
- FrontRightTop, FrontRightBottom
- );
-
- face = face->next;
- setFace( BottomFace,
- BackLeftBottom, FrontLeftBottom,
- FrontRightBottom, BackRightBottom
- );
-
- face = face->next;
- setFace( TopFace,
- BackLeftTop, BackRightTop,
- FrontRightTop, FrontLeftTop
- );
-
- face = face->next;
- setFace( BackFace,
- BackLeftBottom, BackRightBottom,
- BackRightTop, BackLeftTop
- );
-
- return volume;
- }
-
- /*---------------------------------------------------------------------------*/
- /* BBoxClip
- /*---------------------------------------------------------------------------*/
- static void
- BBoxClip( Volume *volume,
- float xmin, float xmax,
- float ymin, float ymax,
- float zmin, float zmax )
- {
- GLdouble equation[4];
-
- #if 1
- equation[0] = 1.; /* x-xmin >=0 */
- equation[1] = 0.;
- equation[2] = 0.;
- equation[3] = -xmin;
- ClipVolume( volume, equation );
-
- equation[0] = -1.; /* -x+xmax >= 0 */
- equation[3] = xmax;
- ClipVolume( volume, equation );
-
- equation[0] = 0.; /* y-ymin >= 0 */
- equation[1] = 1.;
- equation[3] = -ymin;
- ClipVolume( volume, equation );
-
- equation[1] = -1.; /* -y+ymax >= 0 */
- equation[3] = ymax;
- ClipVolume( volume, equation );
-
- equation[1] = 0.; /* z-zmin >= 0 */
- equation[2] = 1.;
- equation[3] = -zmin;
- ClipVolume( volume, equation );
-
- equation[2] = -1.; /* -z+zmax >= 0 */
- equation[3] = zmax;
- ClipVolume( volume, equation );
- #else
- equation[0] = 0.; /* -y+ymax >= 0 */
- equation[1] = -1.;
- equation[2] = 0.;
- equation[3] = ymax;
- ClipVolume( volume, equation );
- #endif
- }
-
- /*---------------------------------------------------------------------------*/
- /* ClipLine3D
- /*---------------------------------------------------------------------------*/
- /*
- compute the 3D intersection of the
- line: (v1,v2)
- line: eq[0]*v->x + eq[1]*v->y + eq[2]*v->z + eq[3] = 0
- (purely mathematical)
- */
- static Vertex *
- ClipLine3D( Vertex *v1, Vertex *v2, GLdouble *eq )
- {
- GLdouble t;
- Vertex *v = alloc_Vertex( NULL );
- v->in = 1;
-
- t = equate(v1,eq);
- if ( t == 0. )
- {
- v->x = v1->x;
- v->y = v1->y;
- v->z = v1->z;
- }
- else
- {
- t = t/(t-equate(v2,eq));
- v->x = v1->x + t*( v2->x - v1->x );
- v->y = v1->y + t*( v2->y - v1->y );
- v->z = v1->z + t*( v2->z - v1->z );
- }
- return v;
- }
-
- /*---------------------------------------------------------------------------*/
- /* ClipVolume
- /*---------------------------------------------------------------------------*/
- static void
- ClipVolume( Volume *volume, GLdouble *equation )
- {
- int i, j, numf, numv, nums;
- Vertex *v, *v0, *v1;
- Segment *segment;
- Face *face;
- Edge *edge, *edge0, *edge1;
-
- if (volume==NULL) return;
- if ((!volume->numVertex) || (!volume->numSegment) || (!volume->numFace))
- return;
-
- volume->numNewSegment = 0;
- volume->firstNewSegment = NULL;
- /*
- test every vertex against clipping plane
- ----------------------------------------
- */
- numv = volume->numVertex;
- v = volume->firstVertex;
- for (i=0; i<numv; i++, v=v->next)
- v->in = (equate(v,equation) >= 0);
- /*
- Now, rework segments
- --------------------
- */
- nums = volume->numSegment;
- segment = volume->firstSegment;
- for (i=0; i<nums; i++, segment=segment->next)
- {
- if (segment->start->in)
- segment->state = (segment->end->in) ? CULLED_IN : CLIPPED_END;
- else
- segment->state = (segment->end->in) ? CLIPPED_START : CULLED_OUT;
-
- if ((segment->state==CLIPPED_START) || (segment->state==CLIPPED_END))
- {
- v = ClipLine3D( segment->start, segment->end, equation);
- volume->lastVertex->next = v;
- v->next = NULL;
- v->last = volume->lastVertex;
- volume->lastVertex = v;
- volume->numVertex++;
-
- if (segment->state==CLIPPED_START) segment->start = v;
- else segment->end = v;
- }
- }
-
- /*
- clip every face of the Volume
- -----------------------------
- */
- #define GETSTATE(edge)\
- ((edge->inverted) ?\
- ((edge->segment->state==CLIPPED_END) ?\
- CLIPPED_START\
- :\
- ((edge->segment->state==CLIPPED_START) ?\
- CLIPPED_END\
- :\
- edge->segment->state\
- )\
- )\
- :\
- edge->segment->state\
- )
-
- numf = volume->numFace;
- face = volume->firstFace;
- for (i=0; i<numf; i++, face=face->next)
- {
- Edge *edge = face->firstEdge;
- int nume = face->numEdge;
- int state = GETSTATE(edge);
-
- switch (state)
- {
- case CULLED_IN:
- case CLIPPED_END:
- if (state!=CLIPPED_END) do
- {
- edge = edge->next;
- state = GETSTATE(edge);
- }
- while ((state!=CLIPPED_END) && (edge!=face->firstEdge));
- if ( state == CLIPPED_END )
- {
- edge0 = edge;
- edge = edge->next;
- state = GETSTATE(edge);
- while ((state!=CLIPPED_START) && (edge!=edge0))
- {
- edge = edge->next;
- state = GETSTATE(edge);
- }
- if (state != CLIPPED_START)
- {
- fprintf(stderr,
- "ERROR: ClipVolume: unable to clip face\n");
- break;
- }
-
- segment = edge0->segment;
- v0 = (edge0->inverted) ? segment->start : segment->end;
- segment = edge->segment;
- v1 = (edge->inverted) ? segment->end : segment->start;
- segment = newSegment( volume, v0, v1 );
-
- edge1 = alloc_Edge( NULL );
- edge1->segment = segment;
- edge1->inverted = (segment->start==v1);
- edge1->next = edge;
- edge1->last = edge0;
- edge = edge->last;
- while (edge != edge0)
- {
- edge = edge->last;
- alloc_Edge( edge->next );
- nume--;
- }
- edge1->next->last = edge1;
- edge1->last->next = edge1;
-
- face->firstEdge = edge1;
- face->numEdge = nume+1;
- }
- break;
-
- case CULLED_OUT:
- case CLIPPED_START:
- if (state != CLIPPED_START) do
- {
- edge = edge->next;
- state = GETSTATE(edge);
- }
- while ((state!=CLIPPED_START) && (edge!=face->firstEdge));
- if ( state != CLIPPED_START )
- {
- for (j=0; j<nume; j++)
- {
- Edge *nextEdge = edge->next;
- alloc_Edge( edge );
- edge = nextEdge;
- }
- face->numEdge = 0;
- face->firstEdge = NULL;
- }
- else
- {
- edge0 = edge;
- edge = edge->next;
- state = GETSTATE(edge);
- while ((state != CLIPPED_END) && (edge!=edge0))
- {
- edge = edge->next;
- state = GETSTATE(edge);
- }
- if (state != CLIPPED_END)
- {
- fprintf(stderr,
- "ERROR: ClipVolume: unable to clip face\n");
- break;
- }
- segment = edge->segment;
- v0 = (edge->inverted) ? segment->start : segment->end;
- segment = edge0->segment;
- v1 = (edge0->inverted) ? segment->end : segment->start;
- segment = newSegment( volume, v0, v1 );
-
- edge1 = alloc_Edge( NULL );
- edge1->segment = segment;
- edge1->inverted = (segment->start==v1);
- edge1->next = edge0;
- edge1->last = edge;
- edge = edge->next;
- while (edge!=edge0)
- {
- edge = edge->next;
- alloc_Edge( edge->last );
- nume--;
- }
- edge1->next->last = edge1;
- edge1->last->next = edge1;
-
- face->firstEdge = edge1;
- face->numEdge = nume+1;
- }
- break;
- }
- }
- /*
- build a new face, made of all the newly created segments
- --------------------------------------------------------
- */
- #ifdef DEV
- fprintf( stderr, "numNewSegment = %d\n", volume->numNewSegment );
- #endif
- if ((nums=volume->numNewSegment) > 0)
- {
- face = newFace( nums, equation );
- edge = face->firstEdge;
- segment = volume->firstNewSegment;
- for (i=0; i<nums; i++)
- {
- edge->segment = segment;
- segment = segment->next;
- edge = edge->next;
- }
- /*
- re-order the edges, so that each segment starts with
- the end of the previous segment (of the previous edge)
- */
- edge0 = face->firstEdge;
- edge0->inverted = 0;
- for (i=0; i<nums-1; i++)
- {
- int found;
- segment = edge0->segment;
- v = (edge0->inverted) ? segment->start : segment->end;
- edge = edge0->next;
- for (found=0, j=i+1; (!found) && (j<nums); j++)
- {
- segment = edge->segment;
- if ((segment->start == v) || (segment->end == v))
- {
- found = 1;
- edge->inverted = (segment->end == v);
- }
- else edge = edge->next;
- }
- if (found)
- {
- edge->next->last = edge->last;
- edge->last->next = edge->next;
- edge->next = edge0->next;
- edge->last = edge0;
- edge->next->last = edge;
- edge->last->next = edge;
- edge0 = edge;
- }
- else
- {
- fprintf(stderr,
- "ERROR::ClipVolume:: unable to close new face\n");
- edge0 = edge0->next;
- }
- }
- face->last = volume->lastFace;
- face->next = NULL;
- volume->lastFace->next = face;
- volume->lastFace = face;
- volume->numFace++;
- }
- /*
- Finally remove all the useless data :
- --------------------------------------
- vertex removed if !(vertex->in)
- segment removed if (segment->state==CULLED_OUT)
- face removed if (face->numEdge==0)
- */
- #define CLEANUP( Type, Func, condition, firstItem, lastItem, numItem )\
- {\
- Type *ptr = firstItem;\
- int num = numItem;\
- for (i=0; i<num; i++)\
- {\
- Type *nextptr = ptr->next;\
- if (condition)\
- {\
- Type *lastptr = ptr->last;\
- if (lastptr) lastptr->next = nextptr;\
- if (nextptr) nextptr->last = lastptr;\
- if (firstItem==ptr) firstItem=nextptr;\
- if (lastItem==ptr) lastItem=lastptr;\
- Func( ptr );\
- numItem--;\
- }\
- ptr = nextptr;\
- }\
- }
-
- CLEANUP(
- Vertex, alloc_Vertex, (!ptr->in),
- volume->firstVertex, volume->lastVertex, volume->numVertex
- );
- CLEANUP(
- Segment, alloc_Segment, (ptr->state==CULLED_OUT),
- volume->firstSegment, volume->lastSegment, volume->numSegment
- );
- CLEANUP(
- Face, alloc_Face, (ptr->numEdge==0),
- volume->firstFace, volume->lastFace, volume->numFace
- );
- }
-
- /*---------------------------------------------------------------------------*/
- /* deleteVolume
- /*---------------------------------------------------------------------------*/
- static void
- deleteVolume( Volume *volume )
- {
- int j,numf;
- Face *face;
-
- if (volume == NULL) return;
-
- #define DELETE( Type, Func, numItem, firstItem )\
- {\
- int i, num = numItem;\
- Type *ptr = firstItem;\
- for (i=0; i<num; i++)\
- {\
- Type *next = ptr->next;\
- Func( ptr );\
- ptr = next;\
- }\
- }
-
- DELETE( Vertex, alloc_Vertex, volume->numVertex, volume->firstVertex );
- DELETE( Segment, alloc_Segment, volume->numSegment, volume->firstSegment );
-
- numf = volume->numFace;
- face = volume->firstFace;
- for (j=0; j<numf; j++)
- {
- Face *nextface = face->next;
- DELETE( Edge, alloc_Edge, face->numEdge, face->firstEdge );
- alloc_Face( face );
- face = nextface;
- }
-
- alloc_Volume( volume );
- }
-
- /*---------------------------------------------------------------------------*/
- /* newSegment
- /*---------------------------------------------------------------------------*/
- static Segment *
- newSegment( Volume *volume, Vertex *v0, Vertex *v1 )
- {
- int i, num = volume->numSegment;
- Segment *segment = volume->firstSegment;
-
- for (i=0; i<num; i++, segment=segment->next)
- {
- if (((segment->start==v0) && (segment->end==v1)) ||
- ((segment->start==v1) && (segment->end==v0)))
- return segment;
- }
-
- segment = alloc_Segment( NULL );
- if (!volume->numNewSegment)
- volume->firstNewSegment = segment;
- volume->numNewSegment++;
-
- segment->state = CULLED_IN;
- segment->start = v0;
- segment->end = v1;
- if (volume->lastSegment == NULL)
- {
- volume->firstSegment = volume->lastSegment = segment;
- segment->last = segment->next = NULL;
- }
- else
- {
- volume->lastSegment->next = segment;
- segment->last = volume->lastSegment;
- volume->lastSegment = segment;
- }
- segment->next = NULL;
- volume->numSegment++;
- }
-
- /*---------------------------------------------------------------------------*/
- /* newFace
- /*---------------------------------------------------------------------------*/
- static Face *
- newFace( int numEdge, GLdouble *equation )
- {
- int i;
- Face *face = alloc_Face( NULL );
- Edge *edge;
-
- face->numEdge = numEdge;
- edge = face->firstEdge = alloc_Edge( NULL );
- for (i=1; i<numEdge; i++)
- {
- edge->next = alloc_Edge( NULL );
- edge->next->last = edge;
- edge = edge->next;
- }
- edge->next = face->firstEdge; /* ring buffer */
- face->firstEdge->last = edge;
-
- if (equation != NULL)
- for (i=0; i<4; i++)
- face->equation[i] = equation[i];
-
- return face;
- }
-
- /*---------------------------------------------------------------------------*/
- /* getMinMaxLat
- /*---------------------------------------------------------------------------*/
- /*
- get min and max z-values of volume
- */
- static int
- getMinMaxLat( Volume *volume, float *latmin, float *latmax )
- {
- int i, num;
- Vertex *v;
- float min, max;
-
- if (volume == NULL) return 0;
- if ((num=volume->numVertex) <= 0) return 0;
- if ((v=volume->firstVertex) == NULL) return 0;
-
- min = max = v->z;
- v = v->next;
- for (i=1; i<num; i++, v=v->next)
- {
- min = INF(min, v->z );
- max = SUP(max, v->z );
- }
-
- *latmin = min;
- *latmax = max;
- }
-
- /*---------------------------------------------------------------------------*/
- /* getMinMaxLon
- /*---------------------------------------------------------------------------*/
- /*
- for a given z=cste line, get min&max x-values of volume
- */
- static int
- getMinMaxLon( Volume *volume, float lat, float *lonmin, float *lonmax )
- {
- int i, num, first_found = 0;
- float dl, lon, lonA, latA, lonB, latB, max, min;
- Segment *segment;
-
- if (volume == NULL) return 0;
- if ((num=volume->numSegment) <= 0) return 0;
- if ((segment=volume->firstSegment) == NULL) return 0;
-
- for (i=0; i<num; i++, segment=segment->next)
- {
- lonA = segment->start->x;
- latA = segment->start->z;
- lonB = segment->end->x;
- latB = segment->end->z;
-
- if ((lat==latA) && (latA==latB))
- {
- if (first_found)
- {
- min = INF( min, INF(lonA,lonB));
- max = SUP( max, SUP(lonA,lonB));
- }
- else
- {
- min = INF(lonA,lonB);
- max = SUP(lonA,lonB);
- first_found = 1;
- }
- }
- else if (latA != latB)
- {
- dl = latB - latA;
- if (((dl>0) && (lat>=latA) && (lat<=latB)) ||
- ((dl<0) && (lat<=latA) && (lat>=latB)))
- {
- lon = lonA + (lonB-lonA)*((lat-latA)/dl);
- if (first_found)
- {
- max = SUP( max, lon );
- min = INF( min, lon );
- }
- else
- {
- max = min = lon;
- first_found = 1;
- }
- }
- }
- }
-
- *lonmin = min;
- *lonmax = max;
- return first_found;
- }
-
- #define CHUNKSIZE_VOL 1
-
- Volume*
- alloc_Volume(
- Volume *ptr
- ) {
- static Volume *store;
- static int free=0;
-
- if(!ptr) {
- if(--free < 0) {
- register int i;
- if((store = (Volume*)malloc(CHUNKSIZE_VOL*sizeof(Volume))) == NULL)
- {fprintf(stderr, "SYSTEM ERROR: malloc (exiting)"); exit(1);}
- for(i=0, ptr=store; i<CHUNKSIZE_VOL-1; ++i, ++ptr)
- ptr->next = ptr+1;
- free += CHUNKSIZE_VOL;
- }
- ptr = store;
- store = store->next;
- }
- else {ptr->next = store; store = ptr; free++;}
- return(ptr);
- }
-
- #define CHUNKSIZE_VERT 12
-
- Vertex*
- alloc_Vertex(
- Vertex *ptr
- ) {
- static Vertex *store;
- static int free=0;
-
- if(!ptr) {
- if(--free < 0) {
- register int i;
- if((store = (Vertex*)malloc(CHUNKSIZE_VERT*sizeof(Vertex))) == NULL)
- {fprintf(stderr, "SYSTEM ERROR: malloc (exiting)"); exit(1);}
- for(i=0, ptr=store; i<CHUNKSIZE_VERT-1; ++i, ++ptr)
- ptr->next = ptr+1;
- free += CHUNKSIZE_VERT;
- }
- ptr = store;
- store = store->next;
- }
- else {ptr->next = store; store = ptr; free++;}
- return(ptr);
- }
-
- #define CHUNKSIZE_EDGE 25
-
- Edge*
- alloc_Edge(
- Edge *ptr
- ) {
- static Edge *store;
- static int free=0;
-
- if(!ptr) {
- if(--free < 0) {
- register int i;
- if((store = (Edge*)malloc(CHUNKSIZE_EDGE*sizeof(Edge))) == NULL)
- {fprintf(stderr, "SYSTEM ERROR: malloc (exiting)"); exit(1);}
- for(i=0, ptr=store; i<CHUNKSIZE_EDGE-1; ++i, ++ptr)
- ptr->next = ptr+1;
- free += CHUNKSIZE_EDGE;
- }
- ptr = store;
- store = store->next;
- }
- else {ptr->next = store; store = ptr; free++;}
- return(ptr);
- }
-
- #define CHUNKSIZE_FACE 8
-
- Face*
- alloc_Face(
- Face *ptr
- ) {
- static Face *store;
- static int free=0;
-
- if(!ptr) {
- if(--free < 0) {
- register int i;
- if((store = (Face*)malloc(CHUNKSIZE_FACE*sizeof(Face))) == NULL)
- {fprintf(stderr, "SYSTEM ERROR: malloc (exiting)"); exit(1);}
- for(i=0, ptr=store; i<CHUNKSIZE_FACE-1; ++i, ++ptr)
- ptr->next = ptr+1;
- free += CHUNKSIZE_FACE;
- }
- ptr = store;
- store = store->next;
- }
- else {ptr->next = store; store = ptr; free++;}
- return(ptr);
- }
-
- #define CHUNKSIZE_SEGMENT 16
-
- Segment*
- alloc_Segment(
- Segment *ptr
- ) {
- static Segment *store;
- static int free=0;
-
- if(!ptr) {
- if(--free < 0) {
- register int i;
- if((store = (Segment*)malloc(CHUNKSIZE_SEGMENT*sizeof(Segment))) == NULL)
- {fprintf(stderr, "SYSTEM ERROR: malloc (exiting)"); exit(1);}
- for(i=0, ptr=store; i<CHUNKSIZE_SEGMENT-1; ++i, ++ptr)
- ptr->next = ptr+1;
- free += CHUNKSIZE_SEGMENT;
- }
- ptr = store;
- store = store->next;
- }
- else {ptr->next = store; store = ptr; free++;}
- return(ptr);
- }
-